
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <memory.h>


#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifi_connect.h"
#include "E53_IA1.h"
#include "MQTTClient.h"
#include "string.h"
#include "wifiiot_adc.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_errno.h"

/*MQTT协议链接设备的三元组*/
#define EXAMPLE_PRODUCT_KEY			"gxbuo8WONui"
#define EXAMPLE_DEVICE_NAME			"temperature-zzz"
#define EXAMPLE_DEVICE_SECRET       "c53a602827c9f794688b45dc23aa0693"

bool webZledFlag = 0; //web端led控制标志位
bool webFansFlag = 0; //web端fans控制标志位
bool webPumpFlag = 0; //web端水泵控制标志位

/* declare the external function aiotMqttSign() */
extern int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret, 
                     	char clientId[150], char username[65], char password[65]);

/***** 获取电压值函数 *****/
static float GetVoltage(void)  //GPIO11
{
    unsigned int ret;
    unsigned short data;

    ret = AdcRead(WIFI_IOT_ADC_CHANNEL_5, &data, WIFI_IOT_ADC_EQU_MODEL_8, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0xff);
    if (ret != WIFI_IOT_SUCCESS)
    {
        printf("ADC Read Fail\n");
    }

    return (float)data * 1.8 * 4 / 4096.0;
}

E53_IA1_Data_TypeDef E53_IA1_Data;
char msgStr[100];//上传数据数组
char RxBuff[50]; //接受的数据数组
bool RxFlag = 0; //接受到消息标志位，接收到消息后才处理消息

/*处理接收的消息,获取有用信息
没考虑到异常问题，只想到的按照理想情况，所以异常时会导致栈溢出，需要对边界处理
有返回值的需要多种考虑，如果不是正常情况怎么办*/

void dealMessage(char* Message){

    //printf("data:%s\r\n",Message);
	char* recName;
	char* recCmd;
	recName = strstr(Message, "name"); 
    //命令格式不对，返回
    if(recName == NULL){
        printf("the form of data is error!\r\n");
        return;
    } 
    /*获取设备名称*/
	recName += 7;
	char name[5];
	int i;
	for(i = 0; i < 4; i++){     
		name[i] = *(recName+ i);
	}
    name[4] = '\0';  //补充结尾标志

    /*获取命令名称*/
	recCmd = strstr(Message, "value");
    if(recCmd == NULL){
        printf("the form of cmd is error!\r\n");
        return;
    } 
    char value; 
	recCmd += 7;
	value = *recCmd;

	 /*开关风扇*/
    if(strcmp("fans",name) == 0){
        if(value == '0'){
            webFansFlag = 0;
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);

        }else if(value == '1'){
            webFansFlag = 1;
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 0);
        }
    /*开关补光灯*/
	}else if(strcmp("zled",name) == 0){
        if(value == '0'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_12, 1);
            webZledFlag = 0;
        }else if(value == '1'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_12, 0);
            webZledFlag = 1;
        }
    /*开关水泵*/
    }else if(strcmp("pump",name) == 0){
        if(value == '0'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 1);
            webPumpFlag = 0;
        }else if(value == '1'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 0);
            webPumpFlag = 1;
        }
    /*开关施肥水泵*/
    }else if(strcmp("manu",name) == 0){
        if(value == '0'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 1);
            webPumpFlag = 0;
        }else if(value == '1'){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 0);
            webPumpFlag = 1;
        }
    }else {
        printf("can not find the command!\r\n");
        return;
    }


}

void cfinish(int sig)
{
	signal(SIGINT, NULL);
    printf("sig is : %d",sig);
	//toStop = 1;
}

/*MQTT消息接收函数,用于接收云端发送来的指令*/
void messageArrived(MessageData* md)
{
	MQTTMessage* message = md->message;

	printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
	printf("%.*s\n", (int)message->payloadlen, (char*)message->payload);
    // %.*s 其中的.*表示显示的精度 对字符串输出(s)类型来说就是宽度  
    // 这个*代表的值由后面的参数列表中的整数型(int)值给出 

    char* rxBuff; //接收数据数组 
    rxBuff = message->payload;  
    int i;
    for(i = 0; i < (int)message->payloadlen; i++){
        RxBuff[i] = *(rxBuff + i);
    }
    RxFlag = 1; //消息标志位置1

}

/*线程1：
1、wifi模块初始化
2、MQTT参数初始化
3、用于连接wifi以及云端服务器，实时接收云服务器下发的命令
*/

void thread1(void){

    WifiConnect("IOT","11111111");
    int rc = 0;

	/* setup the buffer, it must big enough for aliyun IoT platform */
	unsigned char buf[300];
	unsigned char readbuf[300];

	Network n;
	MQTTClient c;
	char *host = EXAMPLE_PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com";
	short port = 443;

	const char *subTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/test2";
	const char *pubTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/test";

	/* invoke aiotMqttSign to generate mqtt connect parameters */
	char clientId[150] = {0};
	char username[65] = {0};
	char password[65] = {0};

	if ((rc = aiotMqttSign(EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, EXAMPLE_DEVICE_SECRET, clientId, username, password) < 0)) {
		printf("aiotMqttSign -%0x4x\n", -rc);
		//return -1;
	}
	printf("clientid: %s\n", clientId);
	printf("username: %s\n", username);
	printf("password: %s\n", password);

	signal(SIGINT, cfinish);
	signal(SIGTERM, cfinish);

	/* network init and establish network to aliyun IoT platform */
	NetworkInit(&n);
	rc = NetworkConnect(&n, host, port);
	printf("NetworkConnect %d\n", rc);

	/* init mqtt client */
	MQTTClientInit(&c, &n, 1000, buf, sizeof(buf), readbuf, sizeof(readbuf));
 
	/* set the default message handler */
	c.defaultMessageHandler = messageArrived;

	/* set mqtt connect parameter */
	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
	data.willFlag = 0;
	data.MQTTVersion = 3;
	data.clientID.cstring = clientId;
	data.username.cstring = username;
	data.password.cstring = password;
	data.keepAliveInterval = 60;
	data.cleansession = 1;
	printf("Connecting to %s %d\n", host, port);

	rc = MQTTConnect(&c, &data);
	printf("MQTTConnect %d, Connect aliyun IoT Cloud Success!\n", rc);
    
    printf("Subscribing to %s\n", subTopic);
	rc = MQTTSubscribe(&c, subTopic, 1, messageArrived);
	printf("MQTTSubscribe %d\n", rc);
 
    unsigned int msgid = 0;
	while(1)
	{   
        
		MQTTYield(&c, 1000);	

        MQTTMessage msg = {
            QOS1, 
            0,
            0,
            0,
            msgStr,//"Hello world",
            strlen(msgStr),
        };
        msg.id = ++msgid;
        rc = MQTTPublish(&c, pubTopic, &msg);
        printf("MQTTPublish %d, msgid %d\n", rc, msgid);
        
        usleep(1000000);
        
	}


}

/*线程2：
1、温湿度传感器初始化
2、光照传感器初始化
3、土壤湿度传感器初始化
4、MQTT参数初始化
5、传感器数据上传至云服务端
6、判断云端下发的指令
*/

void thread2(void){

    float voltage;
    E53_IA1_Init();

    while (1)
    {
        E53_IA1_Read_Data(&E53_IA1_Data);
        voltage = (1.0 - (GetVoltage() / 3.5)) * 100.0;  //土壤湿度值  

        char msg2[100] = "{\"temp\":%.2f,\"humi\":%.2f,\"illum\":%.2f,\"soil\":%.2f}";
        sprintf(msgStr, msg2, E53_IA1_Data.Temperature, E53_IA1_Data.Humidity, E53_IA1_Data.Lux,voltage);
        printf("%s\r\n", msgStr);

        if(E53_IA1_Data.Temperature > 27.1 && webFansFlag == 0){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 0); //开电扇
        }
        else if(E53_IA1_Data.Temperature < 27.1 && webFansFlag == 0){
             GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1); //关电扇
        }

        if(E53_IA1_Data.Lux < 200.0 && webZledFlag == 0){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_12, 0); //开灯
        }
        else if(E53_IA1_Data.Lux > 200.0 && webZledFlag == 0) {
             GpioSetOutputVal(WIFI_IOT_GPIO_IDX_12, 1); //关灯
        }
        if(voltage < 20.0 && webPumpFlag == 0){
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 0); //开水泵
        }
        else if(voltage > 20.0 && webPumpFlag == 0) {
            GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 1); //关水泵
        }

        if(RxFlag){
            RxFlag = 0; //接收到消息标志位清0
            dealMessage(RxBuff);//  "hello:name" "{\"name\":\"fans\",\"value\":0}"
        }
        usleep(1000000);
        
    }
}

/*线程3：
1、初始化风扇、补光灯、水本IO口
2、开启系统运行指示灯
*/

void thread3(void){
     //初始化GPIO
    GpioInit();

    //设置GPIO_2的复用功能为普通GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_GPIO);
    //设置GPIO_2为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_2, WIFI_IOT_GPIO_DIR_OUT);

    //设置GPIO_10的复用功能为普通GPIO  //风扇 
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO);
    //设置GPIO_10为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);

    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_IO_FUNC_GPIO_12_GPIO); //补光灯
    //设置GPIO_12为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_12, WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_12, 1);

    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_GPIO); //浇水
    //设置GPIO_14为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_14, WIFI_IOT_GPIO_DIR_OUT);
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_14, 1);


    while(1){

        //设置GPIO_2输出高电平点亮LED灯
        GpioSetOutputVal(WIFI_IOT_GPIO_IDX_2, 1);
        //延时1s
        usleep(1000000);
        //设置GPIO_2输出低电平熄灭LED灯
        GpioSetOutputVal(WIFI_IOT_GPIO_IDX_2, 0);
        //延时1s
        usleep(1000000);

    }

}


/*****任务创建*****/
static void Thread_example(void)
{
    osThreadAttr_t attr;

    attr.name = "thread1";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 8;
    attr.priority = 25;

    if (osThreadNew((osThreadFunc_t)thread1, NULL, &attr) == NULL)
    {
        printf("Falied to create thread1!\n");
    }

    attr.name = "thread2";
    attr.stack_size = 1024 * 4;
   // attr.priority = 25;
    if (osThreadNew((osThreadFunc_t)thread2, NULL, &attr) == NULL)
    {
        printf("Falied to create thread2!\n");
    }

    attr.name = "thread3";
    attr.stack_size = 1024 * 1;
    if (osThreadNew((osThreadFunc_t)thread3, NULL, &attr) == NULL)
    {
        printf("Falied to create thread3!\n");
    }

}


//开启线程
APP_FEATURE_INIT(Thread_example);